#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ----------------------------------------------------------
# -- This"s User Views
# -- 
# ****************************
# Author: lmay.Zhou
# Blog: www.lmaye.com
# Date: 2018年2月13日 13:59:10
# ----------------------------------------------------------
import datetime
from flask import render_template, flash, redirect, g, url_for, session, request
from flask_babel import gettext, get_locale, refresh
from flask_login import current_user, login_user, logout_user, login_required
from core.app import app, application, lm, oid, db, babel, languages
from core.constant.sys_enum import SysEnum
from core.forms.post_forms import SearchForm
from core.forms.user_forms import LoginForm, EditForm
from core.models.user_model import User
from core.utils import emails
from core.utils import read_config


@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(languages.keys())


@lm.user_loader
def load_user(id):
    """
        load_user 回调

        :param id: User ID
        :return: User
        :rtype: object
    """
    return User.query.get(int(id))


@app.before_request
def before_request():
    g.user = current_user
    if g.user.is_authenticated():
        g.user.last_seen = datetime.datetime.utcnow() + datetime.timedelta(hours=8)
        db.session.add(g.user)
        db.session.commit()
        g.search_form = SearchForm()
    g.locale = get_locale()


@app.route("/", methods=["GET", "POST"])
@app.route("/user/login", methods=["GET", "POST"])
@oid.loginhandler
def login():
    if g.user is not None and g.user.is_authenticated():
        return redirect(url_for("index"))
    form = LoginForm()
    refresh()
    if form.validate_on_submit():
        # flash("Login requested for OpenID=" + form.openid.data + ", remember_me"
        #       + str(form.remember_me.data))
        # return redirect("/home")
        session["remember_me"] = form.remember_me.data
        return oid.try_login(form.openid.data, ask_for=["nickname", "email"])
    return render_template("login.html", title="Sign In", form=form,
                           providers=application["server"]["openid_providers"])


@oid.after_login
def after_login(resp):
    if resp.email is None or resp.email == "":
        flash(gettext("Invalid login. Please try again."))
        return redirect(url_for("login"))
    user = User.query.filter_by(email=resp.email).first()
    if user is None:
        nickname = resp.nickname
        if nickname is None or nickname == "":
            nickname = resp.email.split("@")[0]
        nickname = User.make_valid_nickname(nickname)
        nickname = User.make_unique_nickname(nickname)
        user = User(nickname=nickname, email=resp.email)
        db.session.add(user)
        db.session.commit()
        # make the user follow him/herself
        db.session.add(user.follow(user))
        db.session.commit()
    remember_me = False
    if "remember_me" in session:
        remember_me = session["remember_me"]
        session.pop("remember_me", None)
    login_user(user, remember=remember_me)
    return redirect(request.args.get("next") or url_for("index"))


@app.route("/logout")
def logout():
    logout_user()
    return redirect(url_for("login"))


@app.route("/user/<nickname>")
@app.route("/user/<nickname>/<int:page>")
@login_required
def user(nickname, page=1):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash("User " + nickname + " not found.")
        return redirect(url_for("index"))
    posts = user.posts.paginate(page, SysEnum.POSTS_PER_PAGE.value, False)
    return render_template("user/user.html", user=user, posts=posts)


@app.route("/edit_user", methods=["GET", "POST"])
@login_required
def edit_user():
    form = EditForm(g.user.nickname)
    if form.validate_on_submit():
        g.user.nickname = form.nickname.data
        g.user.about_me = form.about_me.data
        db.session.add(g.user)
        db.session.commit()
        flash("Your changes have been saved.")
        return redirect(url_for("user", nickname=g.user.nickname))
    else:
        form.nickname.data = g.user.nickname
        form.about_me.data = g.user.about_me
    return render_template("user/edit.html", form=form)


@app.route("/article")
@login_required
def article():
    user = g.user
    posts = read_config.read_json(SysEnum.JSON_PATH.value)
    return render_template("user/article.html", title="Home", user=user, articles=posts)


@app.route("/follow/<nickname>")
@login_required
def follow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash("User %s not found." % nickname)
        return redirect(url_for("index"))
    if user == g.user:
        flash("You can\'t follow yourself!")
        return redirect(url_for("user", nickname=nickname))
    u = g.user.follow(user)
    if u is None:
        flash("Cannot follow " + nickname + ".")
        return redirect(url_for("user", nickname=nickname))
    db.session.add(u)
    db.session.commit()
    flash("You are now following " + nickname + "!")
    emails.follower_notification(user, g.user)
    return redirect(url_for("user", nickname=nickname))


@app.route("/unfollow/<nickname>")
@login_required
def unfollow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash("User %s not found." % nickname)
        return redirect(url_for("index"))
    if user == g.user:
        flash("You can\'t unfollow yourself!")
        return redirect(url_for("user", nickname=nickname))
    u = g.user.unfollow(user)
    if u is None:
        flash("Cannot unfollow " + nickname + ".")
        return redirect(url_for("user", nickname=nickname))
    db.session.add(u)
    db.session.commit()
    flash("You have stopped following " + nickname + ".")
    return redirect(url_for("user", nickname=nickname))
